/**
 * @file uart_handler.c
 * @brief 串口通信处理模块实现
 * @version 1.0
 * @date 2023-03-15
 */

#include <stdio.h>        // 新增标准输入输出
#include <unistd.h>
#include "uart_protocol.h"
#include <termios.h>
#include "uart_handler.h"
#include "ice_calculation.h"  // 新增头文件包含
#include <fcntl.h>            // 新增头文件
#include <sys/select.h>       // 新增头文件
#include <string.h>   // 新增memcmp函数
#include <byteswap.h> // 新增字节序转换
#include <arpa/inet.h>  // 新增htons函数声明
#include <endian.h>     // 字节序转换头文件
#include <stdlib.h>
#include <sys/time.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/serial.h>
#include <time.h>
#include "system_utils.h"
#include "simulation.h"    // 新增simulation.h头文件包含

// 标记未使用的变量或函数，避免编译警告
#define UNUSED(x) (void)(x)

// 定义调试宏
#ifdef DEBUG
#define DEBUG_PRINT(fmt, ...) printf("[UART] " fmt, ##__VA_ARGS__)
#else
#define DEBUG_PRINT(fmt, ...)
#endif

// 定义帧头和帧尾常量数组
const uint8_t FRAME_HEADER[2] = {FRAME_HEADER_1, FRAME_HEADER_2};
const uint8_t FRAME_FOOTER[2] = {FRAME_FOOTER_1, FRAME_FOOTER_2};

// 全局配置
static UartConfig g_uart_config = {
    .baud_rate = DEFAULT_BAUD_RATE,
    .timeout_ms = DEFAULT_TIMEOUT_MS,
    .retry_count = DEFAULT_RETRY_COUNT,
    .debug_mode = DEFAULT_DEBUG_MODE
};

// 辅助函数 - 字节序转换（网络字节序到主机字节序）
static float ntoh_float(float net_float) {
    uint32_t temp;
    memcpy(&temp, &net_float, sizeof(float));
    temp = ntohl(temp);
    float host_float;
    memcpy(&host_float, &temp, sizeof(float));
    return host_float;
}

// 辅助函数 - 字节序转换（主机字节序到网络字节序）
static float hton_float(float host_float) {
    uint32_t temp;
    memcpy(&temp, &host_float, sizeof(float));
    temp = htonl(temp);
    float net_float;
    memcpy(&net_float, &temp, sizeof(float));
    return net_float;
}

// 校验和计算实现
uint8_t calculate_checksum(const void* data, size_t length) {
    uint8_t sum = 0;
    const uint8_t* bytes = (const uint8_t*)data;
    for (size_t i = 0; i < length; i++) {
        sum += bytes[i];
    }
    return sum;
}

// 错误码到字符串的转换
extern const char* uart_error_str(int error_code);

// 串口波特率定义
static __attribute__((unused)) const int baudrate_table[][2] = {
    {0,         B0},
    {50,        B50},
    {75,        B75},
    {110,       B110},
    {134,       B134},
    {150,       B150},
    {200,       B200},
    {300,       B300},
    {600,       B600},
    {1200,      B1200},
    {1800,      B1800},
    {2400,      B2400},
    {4800,      B4800},
    {9600,      B9600},
    {19200,     B19200},
    {38400,     B38400},
    {57600,     B57600},
    {115200,    B115200},
    {230400,    B230400},
#ifdef B460800
    {460800,    B460800},
#endif
#ifdef B500000
    {500000,    B500000},
#endif
#ifdef B576000
    {576000,    B576000},
#endif
#ifdef B921600
    {921600,    B921600},
#endif
#ifdef B1000000
    {1000000,   B1000000},
#endif
#ifdef B1152000
    {1152000,   B1152000},
#endif
#ifdef B1500000
    {1500000,   B1500000},
#endif
#ifdef B2000000
    {2000000,   B2000000},
#endif
#ifdef B2500000
    {2500000,   B2500000},
#endif
#ifdef B3000000
    {3000000,   B3000000},
#endif
#ifdef B3500000
    {3500000,   B3500000},
#endif
#ifdef B4000000
    {4000000,   B4000000},
#endif
    {-1,        B0}
};

// 将波特率值转换为波特率宏定义
static __attribute__((unused)) int get_baudrate_const(int baudrate) {
    // 标记为已使用，避免警告
    UNUSED(baudrate);
    
    int i = 0;
    while (baudrate_table[i][0] != -1) {
        if (baudrate_table[i][0] == baudrate) {
            return baudrate_table[i][1];
        }
        i++;
    }
    return B9600; // 默认返回9600
}

// 设置串口（基本版本）
int setup_uart(const char* port) {
    return setup_uart_ex(port, &g_uart_config);
}

// 设置串口（扩展版本）- 适配RK3588
int setup_uart_ex(const char* port, UartConfig* config) {
    if (!port || !config) {
        return UART_ERR_PARAM;
    }

    // 打开串口
    int fd = open(port, O_RDWR | O_NOCTTY);
    if (fd < 0) {
        printf("打开串口失败: %s (错误: %s)\n", port, strerror(errno));
        return -errno;  // 返回系统错误码的负值
    }

    // 配置串口
    struct termios options;
    if (tcgetattr(fd, &options) != 0) {
        printf("获取串口属性失败: %s\n", strerror(errno));
        close(fd);
        return -errno;
    }

    // 设置波特率
    speed_t baud;
    switch (config->baud_rate) {
        case 9600:   baud = B9600;   break;
        case 19200:  baud = B19200;  break;
        case 38400:  baud = B38400;  break;
        case 57600:  baud = B57600;  break;
        case 115200: baud = B115200; break;
        default:     baud = B115200; break;
    }

    cfsetispeed(&options, baud);
    cfsetospeed(&options, baud);

    // 设置数据位、停止位、校验位
    options.c_cflag &= ~PARENB;    // 无奇偶校验
    options.c_cflag &= ~CSTOPB;    // 1位停止位
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;        // 8数据位
    options.c_cflag |= (CLOCAL | CREAD); // 本地连接，启用接收

    // 设置为原始输入模式
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    options.c_iflag &= ~(IXON | IXOFF | IXANY);
    options.c_iflag &= ~(INLCR | ICRNL | IGNCR);  // 不转换换行符
    options.c_oflag &= ~OPOST;

    // 设置读取超时 - 自发自收模式可能需要更长时间
    options.c_cc[VMIN] = 0;
    options.c_cc[VTIME] = 5;  // 0.5秒超时

    // 应用设置
    if (tcsetattr(fd, TCSANOW, &options) != 0) {
        printf("设置串口属性失败: %s\n", strerror(errno));
        close(fd);
        return -errno;
    }

    // 清空缓冲区
    tcflush(fd, TCIOFLUSH);
    
    // RK3588可能需要特殊配置
    if (config->debug_mode) {
        printf("串口[%s]已配置: 波特率=%d, 数据位=8, 停止位=1, 校验=无\n", 
               port, config->baud_rate);
    }

    return fd;
}

// 关闭串口
void close_uart(int fd) {
    if (fd >= 0) {
        // 确保数据发送完成
        tcdrain(fd);
        // 关闭串口
        close(fd);
    }
}

// 请求传感器数据
int request_sensor_data(int fd) {
    if (fd < 0) {
        return UART_ERR_PARAM;
    }

    // 构造请求帧
    RequestFrame req;
    memset(&req, 0, sizeof(req));

    // 设置帧头帧尾
    memcpy(req.header, FRAME_HEADER, sizeof(req.header));
    memcpy(req.footer, FRAME_FOOTER, sizeof(req.footer));

    // 设置命令字和数据长度（0表示无数据）
    memcpy(req.cmd, CMD_REQUEST, sizeof(req.cmd));
    req.data_length = 0;

    // 计算校验和
    req.checksum = calculate_checksum(&req.data_length, 
                                     sizeof(req.data_length) + sizeof(req.cmd));

    // 清空接收缓冲区(防止读取到旧数据)
    tcflush(fd, TCIFLUSH);

    // 发送请求
    ssize_t bytes_written = write(fd, &req, sizeof(req));
    if (bytes_written != sizeof(req)) {
        printf("发送请求失败: %s\n", strerror(errno));
        return -errno;
    }
    
    // 确保数据发送完成
    tcdrain(fd);

    if (g_uart_config.debug_mode) {
        printf("已发送传感器数据请求\n");
    }

    return UART_OK;
}

// 接收数据帧解析
int receive_data(int fd, SensorData* data) {
    if (fd < 0 || !data) {
        return UART_ERR_PARAM;
    }

    // 清空数据结构体
    memset(data, 0, sizeof(SensorData));

    // 为了支持自发自收模式，我们检查两种数据格式：标准协议帧和模拟数据字符串
    
    // 读取缓冲区
    uint8_t buffer[256] = {0};
    ssize_t bytes_read = 0;
    
    // 设置超时
    struct timeval timeout;
    timeout.tv_sec = g_uart_config.timeout_ms / 1000;
    timeout.tv_usec = (g_uart_config.timeout_ms % 1000) * 1000;
    
    fd_set readfds;
    FD_ZERO(&readfds);
    FD_SET(fd, &readfds);
    
    int ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
    if (ret <= 0) {
        // 0表示超时，-1表示错误
        return (ret == 0) ? UART_ERR_TIMEOUT : -errno;
    }
    
    // 读取可用数据
    bytes_read = read(fd, buffer, sizeof(buffer) - 1);
    if (bytes_read <= 0) {
        return -errno;
    }
    
    // 确保字符串以null结尾
    buffer[bytes_read] = '\0';
    
    // 首先尝试解析模拟数据格式 - 修改为新的格式，包含电量、电压和信号强度
    if (strncmp((char*)buffer, "DATA,", 5) == 0) {
        // 解析CSV格式
        int parsed = sscanf((char*)buffer, 
                            "DATA,%f,%f,%f,%f,%f,%f,%f,%f,%d", 
                            &data->temperature,
                            &data->humidity,
                            &data->wind_speed,
                            &data->wind_direction,
                            &data->tension1,
                            &data->tension2,
                            &data->battery_level,
                            &data->voltage,
                            &data->signal_strength);
        
        if (parsed == 9) {  // 增加到9个字段
            // 解析成功
            if (g_uart_config.debug_mode) {
                printf("成功解析模拟数据帧:\n");
                printf("  温度: %.1f℃\n", data->temperature);
                printf("  湿度: %.0f%%\n", data->humidity);
                printf("  风速: %.2fm/s\n", data->wind_speed);
                printf("  风向: %.0f度\n", data->wind_direction);
                printf("  拉力1: %.2fkg\n", data->tension1);
                printf("  拉力2: %.2fkg\n", data->tension2);
                printf("  电量: %.0f%%\n", data->battery_level);
                printf("  电压: %.1fV\n", data->voltage);
                printf("  信号: %ddBm\n", data->signal_strength);
            }
            return UART_OK;
        }
    }
    
    // 如果模拟数据解析失败，尝试标准协议帧解析
    ResponseFrame* resp = NULL;
    
    // 检查数据长度是否合理
    if ((size_t)bytes_read < sizeof(ResponseFrame)) {
        if (g_uart_config.debug_mode) {
            printf("帧长度不足: %zd/%zu\n", bytes_read, sizeof(ResponseFrame));
        }
        return UART_ERR_LENGTH;
    }
    
    // 指向响应帧结构
    resp = (ResponseFrame*)buffer;
    
    // 检查帧头帧尾
    if (memcmp(resp->header, FRAME_HEADER, sizeof(resp->header)) != 0 ||
        memcmp(resp->footer, FRAME_FOOTER, sizeof(resp->footer)) != 0) {
        if (g_uart_config.debug_mode) {
            printf("帧头或帧尾错误\n");
            // 打印收到的内容帮助调试
            printf("接收到 %zd 字节: ", bytes_read);
            for (ssize_t i = 0; i < bytes_read && i < 24; i++) {
                printf("%02X ", buffer[i]);
            }
            printf("\n");
        }
        return UART_ERR_FRAME;
    }
    
    // 检查命令字
    if (memcmp(resp->cmd, CMD_RESPONSE, sizeof(resp->cmd)) != 0) {
        if (g_uart_config.debug_mode) {
            printf("命令字错误: %c%c\n", resp->cmd[0], resp->cmd[1]);
        }
        return UART_ERR_FRAME;
    }
    
    // 检查数据长度
    if (resp->data_length != sizeof(SensorDataPacket)) {
        if (g_uart_config.debug_mode) {
            printf("数据长度错误: %d/%zu\n", resp->data_length, sizeof(SensorDataPacket));
        }
        return UART_ERR_LENGTH;
    }
    
    // 检查校验和
    uint8_t calc_checksum = calculate_checksum(&resp->data_length, 
                                              sizeof(resp->data_length) + 
                                              sizeof(resp->cmd) + 
                                              resp->data_length);
    if (resp->checksum != calc_checksum) {
        if (g_uart_config.debug_mode) {
            printf("校验和错误: 计算值=%02X, 接收值=%02X\n", 
                   calc_checksum, resp->checksum);
        }
        return UART_ERR_CHECKSUM;
    }
    
    // 解析传感器数据
    SensorDataPacket* sensor_packet = (SensorDataPacket*)resp->data;
    
    // 处理字节序转换和单位转换
    data->wind_speed = ntoh_float(sensor_packet->wind_speed);
    data->wind_direction = ntoh_float(sensor_packet->wind_direction);
    data->temperature = ntoh_float(sensor_packet->temperature);
    data->humidity = ntoh_float(sensor_packet->humidity);
    
    // 拉力值单位是kg
    data->tension1 = ntoh_float(sensor_packet->tension1);
    data->tension2 = ntoh_float(sensor_packet->tension2);
    
    // 解析新增的系统参数
    data->battery_level = ntoh_float(sensor_packet->battery_level);
    data->voltage = ntoh_float(sensor_packet->voltage);
    data->signal_strength = ntohl(sensor_packet->signal_strength);
    
    if (g_uart_config.debug_mode) {
        printf("成功解析标准数据帧:\n");
        printf("  温度: %.1f℃\n", data->temperature);
        printf("  湿度: %.0f%%\n", data->humidity);
        printf("  风速: %.2fm/s\n", data->wind_speed);
        printf("  风向: %.0f度\n", data->wind_direction);
        printf("  拉力1: %.2fkg\n", data->tension1);
        printf("  拉力2: %.2fkg\n", data->tension2);
        printf("  电量: %.0f%%\n", data->battery_level);
        printf("  电压: %.1fV\n", data->voltage);
        printf("  信号: %ddBm\n", data->signal_strength);
    }
    
    return UART_OK;
}

// 打印传感器数据
void dump_sensor_data(const SensorData* data) {
    if (!data) return;
    
    printf("===== 传感器数据 =====\n");
    printf("风速: %.2f m/s\n", data->wind_speed);
    printf("风向: %.0f 度\n", data->wind_direction);
    printf("温度: %.1f ℃\n", data->temperature);
    printf("湿度: %.0f %%\n", data->humidity);
    printf("拉力1: %.2f kg\n", data->tension1);
    printf("拉力2: %.2f kg\n", data->tension2);
    printf("电量: %.0f %%\n", data->battery_level);
    printf("电压: %.1f V\n", data->voltage);
    printf("信号: %d dBm\n", data->signal_strength);
    printf("======================\n");
}

/**
 * @brief 初始化UART处理器
 * 
 * 使用配置参数初始化UART通信，建立串口连接
 * 
 * @param config UART配置参数
 * @return int 成功返回0，失败返回负值
 */
int init_uart_handler(UartConfig* config) {
    if (!config || strlen(config->device) == 0) {
        log_message(LOG_LEVEL_ERROR, "UART配置无效或设备名为空");
        return -1;
    }
    
    log_message(LOG_LEVEL_INFO, "初始化UART处理器，设备: %s, 波特率: %d", 
               config->device, config->baud_rate);
    
    // 设置串口连接
    int fd = setup_uart_ex(config->device, config);
    if (fd < 0) {
        log_message(LOG_LEVEL_ERROR, "设置串口失败: %s (错误码: %d)", 
                   config->device, fd);
        return -1;
    }
    
    // 存储文件描述符
    config->device_fd = fd;
    
    log_message(LOG_LEVEL_INFO, "UART通信初始化成功，设备: %s, 文件描述符: %d", 
               config->device, fd);
    
    // 清空缓冲区
    tcflush(fd, TCIOFLUSH);
    
    return 0;
}
